package hu.myai.tick;

import hu.myai.api.tick.AbstractTickProvider;
import hu.myai.model.TickVO;
import hu.myai.util.CommonUtil;
import hu.myai.util.Constans;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipInputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * read the zipped tick date from the file system and propagate the the
 * registered ticks. The files from
 * http://www.forexite.com/free_forex_quotes/forex_history_arhiv.html
 * */
public class ZippedMetastockTick extends AbstractTickProvider {

	/**
	 * The object used when logging debug,errors,warnings and info.
	 * */
	private final Logger log = LoggerFactory.getLogger(this.getClass());

	private String symbol;

	private Date initDate = CommonUtil.parseDate("2009-01-01");

	public ZippedMetastockTick(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public String getSymbol() {
		return symbol;
	}

	public void setSymbol(String symbol) {
		this.symbol = symbol;
	}

	/**
	 * @param initDate
	 *            the initDate to set
	 */
	public void setInitDate(String initDate) {
		this.initDate = CommonUtil.parseDate(initDate);
	}

	@Override
	public void start() {

		int timestamp = 0;
		// create the ordered zip file list from the init date to today
		List<String> fileNameList = getZipFiles(initDate);

		// each zip file is a single day.
		for (String zipFile : fileNameList) {
			try {
				FileInputStream fis = new FileInputStream(zipFile);
				ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis));

				log.debug(zipFile + " processing.");
				// get the files from the zip
				while (zin.getNextEntry() != null) {
					BufferedReader reader = new BufferedReader(new InputStreamReader(zin, Charset.forName("UTF-8")));

					String line;
					// read the file per line
					while ((line = reader.readLine()) != null) {
						timestamp = checkAndPropegate(line, timestamp);
					}

				}
			} catch (IOException e) {
				// if a file is missing than acknowledge it. ..sunday, holiday,
				// ..
				log.debug(zipFile + " skipped.");
			} catch (NumberFormatException e) {
				log.error(e.getMessage());
				throw new RuntimeException("System locale doesn't fit the zipped tick data format.");
			} catch (ParseException e) {
				log.error(e.getMessage());
				throw new RuntimeException("Zipped tick data format has new/unresolved date format.");
			}
		}
	}

	/**
	 * parse a line checks the symbol and propagate the the registered listeners
	 * */
	private int checkAndPropegate(String line, int timestamp) throws NumberFormatException, ParseException {

		String[] itemArray = line.split(",");
		if (symbol.equals(itemArray[0].trim())) {
			SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");

			TickVO tick;
			tick = new TickVO(new Double(itemArray[3]), new Double(itemArray[4]), new Double(itemArray[5]), new Double(itemArray[6]), null,
					formatter.parse(itemArray[1] + itemArray[2]), timestamp++);

			log.debug("in="+tick.toString());
			propegateTick(tick);

		}
		return timestamp;
	}

	/**
	 * make a ordered list out from zipped tick source files
	 * */
	private List<String> getZipFiles(Date fromDate) {

		int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
		SimpleDateFormat formatter = new SimpleDateFormat("ddMMyy");
		List<String> fileNames = new ArrayList<String>();
		long today = (new Date()).getTime();

		// one file contains one day, so iterate fromDate to today
		for (long i = fromDate.getTime(); i < today; i += MILLIS_IN_DAY) {
			fileNames.add(Constans.dataPath + formatter.format(new Date(i)) + ".zip");
		}

		return fileNames;
	}

	/**
	 * main for test
	 * */
	public static void main(String[] argv) throws ParseException {

		ZippedMetastockTick tickSource = new ZippedMetastockTick("Dummy");
		SimpleDateFormat formatter = new SimpleDateFormat(Constans.dateFormat);

		tickSource.initDate = formatter.parse("2009-01-03");
		tickSource.symbol = "EURUSD";

		tickSource.start();
	}

}
